/*
 * Copyright (C) 2007-2008 Alessandro Melandri
 * 
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package net.melandri.jtextfileparser.beans;

import java.io.FileNotFoundException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;

import net.melandri.jtextfileparser.utils.JTextFileParserException;

/**
 * With this class you can parse and manage delimited textfiles.<br>
 * Since version 1.3 you can also build TextFiles objects from an ArrayList of Row objects or a Resulset
 * 
 * <p><strong>Usage</strong></p>
 * 
 * <pre>
 * TextFile myFile = new TextFile("C:\\temp\\","miFile.csv");
 * </pre>
 * 
 * @author Alessandro Melandri
 * @version 1.3
 */
public class TextFile extends TextFileManager {

	private String fileName;
	private ArrayList rows;
	private Row headerRow;
	private boolean hasHeader = false;


	/**
	 * Builds a TextFile object from the specified text file.
	 * 
	 * @param filename Name of the file
	 * @param filePath Path where the file is stored.
	 * @param sep Separator beetween fields.
	 */
	public TextFile(String fileName, String filePath, String sep) throws FileNotFoundException {
		super(fileName, filePath, sep);
		this.fileName = fileName;
		this.rows = parse(1);
	}



	/**
	 * Builds a TextFile object from the specified text file.
	 * 
	 * @param filename Name of the file
	 * @param filePath Path where the file is stored.
	 * @param sep Separator beetween fields.
	 * @param hasHeader Switch to specify if the file has a header line
	 */
	public TextFile(String fileName, String filePath, String sep, boolean hasHeader) throws FileNotFoundException {
		super(fileName, filePath, sep);
		this.hasHeader = hasHeader;
		this.fileName = fileName;
		this.rows = parse(0);

		if (hasHeader) {
			this.headerRow = (Row) this.rows.get(0);
			this.rows.remove(0);
		}
	}



	/**
	 * Builds a TextFile from an ArrayList of Rows objects
	 * 
	 * @param rows ArrayList of Row objects
	 * @param sep Fields separator
	 * @since 1.3
	 */
	public TextFile(ArrayList rows, String sep) {
		super(sep);

		this.rows = rows;
	}



	/**
	 * Builds a TextFile from a Resultset. Every field will be converted to String
	 * 
	 * @param rows Resultset
	 * @param sep Fields separator
	 * @since 1.3
	 */
	public TextFile(ResultSet rs, String sep) {

		super(sep);

		this.rows = new ArrayList();

		try {

			ResultSetMetaData rsmd = rs.getMetaData();
			int fieldsNum = rsmd.getColumnCount();

			while (rs.next()) {

				Row row = new Row(sep);
				String[] fields = new String[fieldsNum];

				for (int i = 1; i <= fieldsNum; i++) {

					if (rs.getString(i) != null)
						fields[i - 1] = rs.getString(i);
					else
						fields[i - 1] = "";
				}

				row.setFields(fields);

				this.rows.add(row);
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}
	}



	/**
	 * Returns the specified row as a String
	 * 
	 * @param rowNumber number of the row in the file
	 * @return Returns a String with the original row
	 */
	public String getStringRow(int rowNumber) throws JTextFileParserException {

		Row thisRow = null;

		try {
			thisRow = (Row) rows.get(rowNumber);
		} catch (IndexOutOfBoundsException e) {
			e.printStackTrace();
			throw new JTextFileParserException("You've specifed a row ID greater than the total row number");
		}


		return thisRow.getStringRow();
	}



	/**
	 * Returns the specified row as a Row object
	 * 
	 * @param ronNumber number of the row in the file
	 * @return Returns the corresponding Row object
	 */
	public Row getRow(int rowNumber) {
		return (Row) rows.get(rowNumber);
	}



	/**
	 * @return Returns an ArrayList of Row objects
	 */
	public ArrayList getRows() {
		return rows;
	}



	/**
	 * Replaces all rows int he text file.
	 * 
	 * @param rows ArrayList of rows objects
	 * @since 1.2
	 */
	public void replaceRows(ArrayList rows) {
		this.rows = rows;
	}



	/**
	 * Returns the number of rows in the file
	 * 
	 * @return Returns the number of rows in the file
	 */
	public int lenght() {
		return rows.size();
	}



	/**
	 * Checks if all the rows have the same number of fields
	 * 
	 * @return Returns true if all the the rows have the same number of fields, otherwise it returns false
	 */
	public boolean checkRowsLength() {

		boolean check = true;

		Iterator it = rows.iterator();
		int sizeHelper = 0;

		while (it.hasNext() && check) {

			Row thisRow = (Row) it.next();
			int size = thisRow.getFields().length;

			if (sizeHelper == 0)
				sizeHelper = size;
			else if (size != sizeHelper)
				check = false;
		}

		return check;
	}



	/**
	 * Checks if all the rows have the specified number of fields
	 * 
	 * @param fieldsNumber The number of expected fields in a row.
	 * @return Returns an ArrayList of rows that don't have the specified number of fields
	 */
	public ArrayList checkRowsLength(int fieldsNumber) {

		ArrayList wrongRows = new ArrayList();

		Iterator it = rows.iterator();

		while (it.hasNext()) {

			Row thisRow = (Row) it.next();

			if (thisRow.getFields().length != fieldsNumber)
				wrongRows.add(thisRow);
		}

		return wrongRows;
	}



	/**
	 * Checks if the specified field has the same length in every row.
	 * 
	 * @param fieldPosition The field to check (numeration starts from 0)
	 * @param fieldLength Expected field length
	 * 
	 * @return Returns an ArraList of Rows.
	 */
	public ArrayList checkField(int fieldPosition, int fieldLength) {

		ArrayList wrongRows = new ArrayList();

		Iterator it = rows.iterator();

		while (it.hasNext()) {

			Row thisRow = (Row) it.next();
			String field = (String) thisRow.getFields()[fieldPosition];

			if (field.length() != fieldLength)
				wrongRows.add(thisRow);
		}

		return wrongRows;
	}



	/**
	 * Creates a copy of the text file
	 * 
	 * @param fileName Name of the file
	 * @param filePath Path of the file
	 */
	public void write(String fileName, String filePath) {
		write(this.rows, fileName, filePath, null, null);
	}



	/**
	 * Creates a copy of the text file using the specified fields separator
	 * 
	 * @param fileName Name of the file
	 * @param filePath Path of the file
	 * @param sep Fields separator
	 */
	public void write(String fileName, String filePath, String sep) {
		write(this.rows, fileName, filePath, sep, null, null);
	}



	/**
	 * Creates a new text file
	 * 
	 * @param fileName Name of the file
	 * @param filePath Path of the file
	 * @param rowindex Array of integer containing the indexes of the rows to be exported. Rows indexes start from zero.
	 */
	public void write(String fileName, String filePath, int[] rowindex) {
		write(this.rows, fileName, filePath, rowindex, null);
	}



	/**
	 * Creates a new text file
	 * 
	 * @param fileName Name of the file
	 * @param filePath Path of the file
	 * @param rowindex Array of integer containing the indexes of the rows to be exported. Rows indexes start from zero.
	 * @param sep Fields separator
	 */
	public void write(String fileName, String filePath, int[] rowindex, String sep) {
		write(this.rows, fileName, filePath, sep, rowindex, null);
	}



	/**
	 * Creates a new text file
	 * 
	 * @param fileName Name of the file
	 * @param filePath Path of the file
	 * @param rowindex Array of integer containing the indexes of the rows to be exported. Rows indexes start from zero.
	 * @param fieldindex Array of integer containing the indexes of the fields to be exportes. Fields indexes start from zero.
	 */
	public void write(String fileName, String filePath, int[] rowindex, int[] fieldindex) {
		write(this.rows, fileName, filePath, rowindex, fieldindex);
	}



	/**
	 * Creates a new text file
	 * 
	 * @param fileName Name of the file
	 * @param filePath Path of the file
	 * @param rowindex Array of integer containing the indexes of the rows to be exported. Rows indexes start from zero.
	 * @param fieldindex Array of integer containing the indexes of the fields to be exportes. Fields indexes start from zero.
	 * @param sep Fields separator
	 */
	public void write(String fileName, String filePath, int[] rowindex, int[] fieldindex, String sep) {
		write(this.rows, fileName, filePath, sep, rowindex, fieldindex);
	}



	/**
	 * Exports the text file to an HTML file
	 * 
	 * @param rows Rows to be included in the new file
	 * @param fileName The name of the file to be created
	 * @param filePath The path where the file will be created
	 * @param title Title of the html page
	 * @param before Text before the data table (text or HTML)
	 * @param after Text after the data table (text or HTML)
	 */
	public void exportHTML(String fileName, String filePath, String title, String before, String after) {
		writeHTML(this.rows, fileName, filePath, title, before, after);
	}



	/**
	 * Exports the text file to an HTML file
	 * 
	 * @param rows Rows to be included in the new file
	 * @param fileName The name of the file to be created
	 * @param filePath The path where the file will be created
	 * @param title Title of the html page
	 * @param before Text before the data table (text or HTML)
	 * @param after Text after the data table (text or HTML)
	 * @param rowindex Array of integer containing the indexes of the rows to be exported. Rows indexes start from zero.
	 */
	public void exportHTML(String fileName, String filePath, String title, String before, String after, int[] rowindex) {
		writeHTML(this.rows, fileName, filePath, title, before, after, rowindex, null);
	}



	/**
	 * Exports the text file to an HTML file
	 * 
	 * @param fileName The name of the file to be created
	 * @param filePath The path where the file will be created
	 * @param title Title of the html page
	 * @param before Text before the data table (text or HTML)
	 * @param after Text after the data table (text or HTML)
	 * @param rowindex Array of integer containing the indexes of the rows to be exported. Rows indexes start from zero.
	 * @param fieldindex Array of integer containing the indexes of the fields to be exportes. Fields indexes start from zero.
	 */
	public void exportHTML(String fileName, String filePath, String title, String before, String after, int[] rowindex, int[] fieldindex) {
		writeHTML(this.rows, fileName, filePath, title, before, after, rowindex, fieldindex);
	}



	/**
	 * @return The name of the file
	 */
	public String getFileName() {
		return fileName;
	}



	/**
	 * @return Returns the header row
	 */
	public Row getHeaders() {
		return headerRow;
	}



	/**
	 * Checks if the TextFile has an header row
	 * 
	 * @since 1.3
	 */
	public boolean hasHeader() {
		return hasHeader;
	}

}
